package com.supergzt.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.supergzt.constant.TimeConstants;
import com.supergzt.service.RedissonService;
import org.redisson.api.RKeys;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 张钧
 * @Description
 * @create 2022-10-24 20:34
 */
@Component
public class RedissonServiceImpl implements RedissonService {
    @Resource
    RedissonClient redissonClient;

    /**
     * 保存键值对
     * @param key 键
     * @param value 值
     * @param time 过期时间（秒）
     * @param <T> 返回值类型
     */
    @Override
    public <T> void setString(String key, T value, Long time) {
        String s = JSON.toJSONString(value);
        redissonClient.getBucket(key).set(s, time, TimeUnit.SECONDS);
    }

    /**
     * 获取值
     * @param key 键
     * @param typeReference 获取值类型
     * @return 值
     * @param <T> 值类型
     */
    @Override
    public <T> T getString (String key,TypeReference<T> typeReference){
        String o = (String) redissonClient.getBucket(key).get();
        return typeReference.parseObject(o);
    }

    /**
     * 获取值 (已废弃)
     * @param key 键
     * @param clazz 获取值类型
     * @return 值
     * @param <T> 值类型
     */
    public <T> T getString(String key, Class<T> clazz) {
        String o = (String) redissonClient.getBucket(key).get();
        return JSON.parseObject( o,clazz);
    }

    /**
     * 移除键值对
     * @param tokenKey 键
     */
    @Override
    public void removeString(String tokenKey) {
        redissonClient.getBucket(tokenKey).delete();
    }

    /**
     * 获取并删除值
     * @param key 键
     * @param clazz 类型
     * @return 值
     * @param <T> 值类型
     */
    @Override
    public <T> T getStringAndDelete(String key, Class<T> clazz) {
        String o = (String) redissonClient.getBucket(key).getAndDelete();
        return JSON.parseObject( o,clazz);
    }

    /**
     * 获取并且增加
     *
     * @param key 键
     * @return 值（Long）
     */
    @Override
    public Long getAndIncrease(String key) {
        redissonClient.getAtomicLong(key).expire(Duration.ofHours(TimeConstants.DAY_HOURS - Integer.parseInt(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH")))));
        return redissonClient.getAtomicLong(key).getAndIncrement();
    }

    /**
     * 扫描符合规则的键
     * @param scanKey 规则
     * @return 键列表
     */
    @Override
    public List<String> scanString(String scanKey) {
        RKeys keys = redissonClient.getKeys();
        List<String> returnKeys = new ArrayList<>();
        keys.getKeysByPattern(scanKey).forEach(returnKeys::add);
        return returnKeys;
    }

    /**
     * 移除多个键
     * @param users 键列表
     */
    @Override
    public void removeStringList(List<String> users) {
        users.forEach(this::removeString);
    }

    @Override
    public RLock getLock(String lock) {
        return redissonClient.getLock(lock);
    }

}
